%% @author Hee Yeon Cho <aposto@nexon.co.kr>
%% @copyright 2009 Nexon Corporation.

%% @doc 
%%      
	
-module (savage_client).
-behaviour(gen_fsm).
-author('aposto@nexon.co.kr').

%% API
-include("session.hrl").

%% External functions
% gen_fsm callbacks
-export([init/1, handle_info/3, handle_event/3, handle_sync_event/4, terminate/3, code_change/4]).
 
-export([start/1, stop/1, start_link/1, test/0]).

-export([wait_for_auth/2, auth/2]).

-record( state, {session, auth=false} ).

%% c(savage_client, [debug_info, {d,'TEST'}]). 
%%  eunit:test(savage_client, [verbose]).

%-define(DBGFSM, true).
-ifdef(DBGFSM).
-define(FSMOPTS, [{debug, [trace]}]).
-else.
-define(FSMOPTS, []).
-endif.

start(Args) ->
	gen_fsm:start( ?MODULE, Args, []).
	
start_link(Sock) ->
	gen_fsm:start_link( ?MODULE, [Sock], ?FSMOPTS ). %{local, ?MODULE}, 

stop(FsmRef)->
	gen_fsm:send_all_state_event(FsmRef, stop).
	
init(Sock) ->
	process_flag(trap_exit, true),
	io:format("init  ~p  ~p~n", [?MODULE, Sock] ),
	%exit( {Sock, auth_timeout} )
	%Pid = spawn_link(fun() -> loop() end),
	{ok, wait_for_auth, #state{}}.

%loop(S = #state{auth=false}) ->	

loop(State) ->	
	receive
		{recv, Bin} ->
			%packet handle
			io:format("$ recv ~p~n", [State#session.name]),
			try 
				ok = tcp_handler:handle(Bin)				
			catch 
				Any -> 
					io:format("$ exception ~p~n", [Any]),
					exit( {State#session.tcp, Any} )
			end,
			loop(State);
		{error, Reason} ->
			io:format("$ client error ~p:~p:~p~n", [State#session.name,self(), Reason])
	end.


%
%game
%dead

test() ->
	 
	{ok, Fsm} = start_link(75),
	io:format("FSM => ~p~n", [Fsm]),
	timer:sleep(100),
	gen_fsm:send_event(Fsm, auth),
	timer:sleep(100),
	gen_fsm:send_event(Fsm, stop),
	timer:sleep(100),
	
	ok.

terminate(Reason, StateName, State) ->
	io:fwrite("gen_fsm called ~w:terminate(~w, ~w, ~w)~n",
		[?MODULE, Reason, StateName, State]),
	ok.
	
code_change(OldVsn, StateName, State, Extra) ->
	io:fwrite("gen_fsm called ~w:code_change(~w, ~w, ~w, ~w)~n",
		[?MODULE, OldVsn, StateName, State, Extra]),
	{ok, StateName, State}.
	
handle_info(Info, StateName, StateData) ->
	io:fwrite("#handle_info gen_fsm called ~w:handle_info(~w, ~w, ~w)~n",
		[?MODULE, Info, StateName, StateData]),
	{next_state, StateName, StateData}.


handle_event(stop, _StateName, StateData) ->
	io:format("* #handle_event (stop) ~n"),
	{stop, normal, StateData};
handle_event(Event, StateName, StateData) ->
	io:fwrite("#handle_sync_event called ~w:handle_event(~w, ~w, ~w)~n",
		[?MODULE, Event, StateName, StateData]),
	{next_state, StateName, StateData}.
handle_sync_event(Event, From, StateName, StateData) ->
	io:fwrite("#handle_sync_event  gen_fsm called ~w:handle_sync_event(~w, ~w, ~w, ~w)~n",
		[?MODULE, Event, From, StateName, StateData]),
	{next_state, StateName, StateData}.			
	
%% Internal functions
wait_for_auth(auth, State) -> 
	io:fwrite( " ^wwait_for_auth function event auth ~n" ),
	{next_state, auth, State};
wait_for_auth(timeout, State) ->
	{stop, normal, State};	
wait_for_auth(Event, State) -> 
	io:fwrite( " ^wait_for_auth event auth ~n" ),
	{next_state, connect, State}.
	
auth(Event, State) -> 
	io:format( " ^auth function event ~p~n", [Event] ),
	{stop, normal, State}.	